// 1.数据逻辑
/* 
  商品价格、商品数量、商品总价和购物车中的结算总价这些都与商品的数据
  息息相关，可以直接将这些属性或方法直接打包成类，便于直接操作数据
  另外，在数据渲染或数据变动中，不要操作原始数据
*/

// 1.1封装单件商品类class(使用构造函数也可)
class UiGood {
  constructor(data) {
    this.data = data;
    this.choose = 0;
  }
  // 获取商品总价方法
  getTotalPrice() {
    return (this.data.price * 100 * this.choose) / 100;
  }
  // 判断是否选中商品方法,方便加减按钮的样式变化
  isChoose() {
    return this.choose > 0;
  }
  // 增加商品数量方法
  increase() {
    this.choose++;
  }
  // 减少商品数量方法
  decrease() {
    // 需要判断是否等于0，等于0就不能 -- 了
    if (this.choose === 0) return;
    this.choose--;
  }
}
// const uigood = new Uigood(goods[0]);
// console.log(uigood);

// 1.2封装整个ui界面数据
class UiData {
  constructor(data) {
    // 1.将所有的商品信息存入data中
    this.data = data.map((item) => {
      const uig = new UiGood(item);
      return uig;
    });

    // 2.设置结算门槛
    (this.minTotalPrice = 30),
      // 3.设置配送门槛
      (this.deliverPrice = 5);
  }

  // 获取结算总价方法
  getAllGoodsTotalPrice() {
    return this.data.reduce((prve, item) => {
      return prve + item.getTotalPrice();
    }, 0);
  }

  // 判断该商品是否被选中
  isChoose(index) {
    return this.data[index].isChoose();
  }

  // 增加某件商品数量方法
  increase(index) {
    // 调用单件商品中的商品数量增加方法
    this.data[index].increase();
  }

  // 减少某件商品数量方法
  decrease(index) {
    // 调用单件商品中的商品数量减少方法
    this.data[index].decrease();
  }

  // 获取所有商品的数量（总件数）
  getAllGoodsNumber() {
    // 累计求和所有商品的数量
    const num = this.data.reduce((prev, item) => {
      return prev + item.choose;
    }, 0);
    // console.log(num);
    return num;
  }

  // 判断购物车中是否有商品方法
  hasGoodInCar() {
    // 判断总件数是否大于零
    return getAllGoodsNumber() > 0;
  }

  // 判断是否已经达到最低结算总价方法
  isCrossMinTotalPrice() {
    return this.getAllGoodsTotalPrice() > this.minTotalPrice;
  }
}
// const uigoods = new UiData(goods);

// 1.3创建ui界面对象
class Ui {
  constructor(data) {
    // 获取所有的ui界面数据
    this.uidata = data;
    // 2.获取需要操作的dom元素
    this.doms = {
      goodslist: document.querySelector(".goods-list"),
      shopcar: document.querySelector(".footer-car"),
      allGoodsTotalPrice: document.querySelector(
        ".footer-car-price .footer-car-total"
      ),
      deliverPrice: document.querySelector(".footer .footer-car-tip"),
      footerPay: document.querySelector(".footer-pay"),
      footercar: document.querySelector(".footer-car"),
    };

    // 一旦实例化ui界面就要直接调用renderGoods渲染商品数据
    this.renderGoods();
    // 一旦调用实例对象，就会监听事件
    this.eventListener();

    // 获取跳跃的目标坐标
    this.jumpTarget = this.doms.footercar.getBoundingClientRect();

    // 更新购物车
    this.upShopCar();
  }

  // 监听各种事件
  eventListener() {
    this.doms.shopcar.addEventListener("animationend", function () {
      // console.log("over");
      this.classList.remove("animate");
    });
  }

  // 渲染商品方法
  renderGoods() {
    // console.log(this.doms.goodslist);
    // console.log(this.uidata);
    this.doms.goodslist.innerHTML = this.uidata.data
      .map((item, index) => {
        console.log(item);
        const {
          choose,
          data: { desc, favorRate, pic, price, sellNumber, title },
        } = item;

        return `
          <div class="goods-item">
            <img src="${pic}" alt="" class="goods-pic" />
            <div class="goods-info">
              <h2 class="goods-title">${title}</h2>
              <p class="goods-desc">
                ${desc}
              </p>
              <p class="goods-sell">
                <span>月售 ${sellNumber}</span>
                <span>好评率${favorRate}%</span>
              </p>
              <div class="goods-confirm">
                <p class="goods-price">
                  <span class="goods-price-unit">￥</span>
                  <span>${price}</span>
                </p>
                <div class="goods-btns">
                  <i data-i="${index}" class="iconfont i-jianhao"></i>
                  <span>${choose}</span>
                  <i data-i="${index}" class="iconfont i-jiajianzujianjiahao"></i>
                </div>
              </div>
            </div>
          </div>
      `;
      })
      .join("");
  }

  // 某件商品增加渲染方法
  increase(index) {
    this.uidata.increase(index);
    // 商品增加立马调用 更新商品数据渲染方法
    this.upGoodsData(index);
    // 调用更新购物车数据渲染方法
    this.upShopCar();
    // 调用跳跃方法
    this.jump(index);
  }

  // 某件商品减少渲染方法
  decrease(index) {
    this.uidata.decrease(index);
    // 商品增加立马调用 更新商品数据渲染方法
    this.upGoodsData(index);
    // 调用更新购物车数据渲染方法
    this.upShopCar();
  }

  // 更新商品数据渲染方法
  upGoodsData(index) {
    if (this.uidata.isChoose(index)) {
      //由于每个商品项是动态生成，所以无法直接获取，只能通过子节点访问
      this.doms.goodslist.children[index].classList.add("active");
    } else {
      this.doms.goodslist.children[index].classList.remove("active");
    }

    // 更新商品数量数据
    const item = this.doms.goodslist.children[index];
    item.querySelector(
      ".goods-btns span"
    ).innerHTML = `${this.uidata.data[index].choose}`;
  }

  // 更新购物车数据渲染
  upShopCar() {
    // 根据商品总件数来判断是否购物车改变状态
    const allGoodsNumber = this.uidata.getAllGoodsNumber();
    const shopcar = this.doms.shopcar;
    if (allGoodsNumber > 0) {
      shopcar.classList.add("active");
      // 展示商品件数
      shopcar.querySelector(
        ".footer-car-badge"
      ).innerHTML = `${allGoodsNumber}`;
    } else {
      shopcar.classList.remove("active");
    }

    //展示商品总价
    const allGoodsTotalPrice = this.uidata.getAllGoodsTotalPrice().toFixed(2);
    this.doms.allGoodsTotalPrice.innerHTML = `${allGoodsTotalPrice}`;

    // 展示配送费
    this.doms.deliverPrice.innerHTML = `配送费￥${this.uidata.deliverPrice}`;

    // 结算总价模块数据渲染
    const totalPrice = this.uidata.getAllGoodsTotalPrice();
    if (totalPrice >= this.uidata.minTotalPrice) {
      this.doms.footerPay.classList.add("active");
    } else {
      this.doms.footerPay.classList.remove("active");
      const gap = (this.uidata.minTotalPrice - totalPrice).toFixed(2);
      this.doms.footerPay.querySelector(
        "span"
      ).innerHTML = `还差￥${gap}元起送`;
    }
  }

  carAnimation() {
    // 添加购物车动画
    this.doms.shopcar.classList.add("animate");
  }

  // 跳跃动画
  jump(index) {
    // console.log(111);
    // 设置对应商品加号起始坐标
    const startCoordinate = this.doms.goodslist.children[index]
      .querySelector(".i-jiajianzujianjiahao")
      .getBoundingClientRect();
    // console.log(startCoordinate);

    // 创建跳跃的盒子
    const div = document.createElement("div");
    div.classList.add("add-to-car");
    const i = document.createElement("i");
    i.className = "iconfont i-jiajianzujianjiahao";
    div.appendChild(i);
    // console.log(div);

    // 要实现抛物线,div控制横坐标运动,i控制纵坐标运动
    div.style.transform = `translateX(${startCoordinate.left}px)`;
    i.style.transform = `translateY(${startCoordinate.top}px)`;

    // 追加到body中
    document.body.appendChild(div);

    // 强行渲染
    // div.clientWidth

    // 下一帧页面渲染时执行回调函数，性能较好
    window.requestAnimationFrame(() => {
      // 设置对应商品加号最终坐标
      div.style.transform = `translateX(${
        this.jumpTarget.left + this.jumpTarget.width / 2
      }px)`;
      i.style.transform = `translateY(${
        this.jumpTarget.top + this.jumpTarget.height / 5
      }px)`;
    });

    // 过渡动画完成之后删除div
    let that = this;
    div.addEventListener(
      "transitionend",
      function () {
        this.remove();
        // 调用更新购物车数据渲染方法
        that.carAnimation();
      },
      {
        once: true, // 事件仅触发一次
      }
    );
  }
}

const ui = new Ui(new UiData(goods));

// 添加事件
document.querySelector(".goods-list").addEventListener("click", (e) => {
  if (e.target.classList.contains("i-jiajianzujianjiahao")) {
    ui.increase(e.target.dataset.i);
  } else if (e.target.classList.contains("i-jianhao")) {
    ui.decrease(e.target.dataset.i);
  }
});
